<meta charset="utf-8">
(#) Not overriding abstract methods on older platforms

!!! ERROR: Not overriding abstract methods on older platforms
   This is an error.

Id
:   `OverrideAbstract`
Summary
:   Not overriding abstract methods on older platforms
Severity
:   Error
Category
:   Correctness
Platform
:   Android
Vendor
:   Android Open Source Project
Feedback
:   https://issuetracker.google.com/issues/new?component=192708
Since
:   0.2.0 (October 2014)
Affects
:   Kotlin and Java files
Editing
:   This check runs on the fly in the IDE editor
Implementation
:   [Source Code](https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/OverrideConcreteDetector.java)
Tests
:   [Source Code](https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/OverrideConcreteDetectorTest.java)

To improve the usability of some APIs, some methods that used to be
`abstract` have been made concrete by adding default implementations.
This means that when compiling with new versions of the SDK, your code
does not have to override these methods.

However, if your code is also targeting older versions of the platform
where these methods were still `abstract`, the code will crash. You must
override all methods that used to be abstract in any versions targeted
by your application's `minSdkVersion`.

(##) Example

Here is an example of lint warnings produced by this check:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~text
src/test/pkg/OverrideConcreteTest.java:23:Error: Must override
android.service.notification.NotificationListenerService.onNotificationPosted(android.service.notification.StatusBarNotification):
Method was abstract until 21, and your minSdkVersion is 18
[OverrideAbstract]
    private static class MyNotificationListenerService2 extends NotificationListenerService {
                         ------------------------------
src/test/pkg/OverrideConcreteTest.java:30:Error: Must override
android.service.notification.NotificationListenerService.onNotificationRemoved(android.service.notification.StatusBarNotification):
Method was abstract until 21, and your minSdkVersion is 18
[OverrideAbstract]
    private static class MyNotificationListenerService3 extends NotificationListenerService {
                         ------------------------------
src/test/pkg/OverrideConcreteTest.java:37:Error: Must override
android.service.notification.NotificationListenerService.onNotificationPosted(android.service.notification.StatusBarNotification):
Method was abstract until 21, and your minSdkVersion is 18
[OverrideAbstract]
    private static class MyNotificationListenerService4 extends NotificationListenerService {
                         ------------------------------
src/test/pkg/OverrideConcreteTest.java:57:Error: Must override
android.service.notification.NotificationListenerService.onNotificationRemoved(android.service.notification.StatusBarNotification):
Method was abstract until 21, and your minSdkVersion is 18
[OverrideAbstract]
    private static class MyNotificationListenerService7 extends MyNotificationListenerService3 {
                         ------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Here is the source file referenced above:

`src/test/pkg/OverrideConcreteTest.java`:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~java linenumbers
package test.pkg;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.os.Build;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class OverrideConcreteTest {
    // OK: This one specifies both methods
    private static class MyNotificationListenerService1 extends NotificationListenerService {
        @Override
        public void onNotificationPosted(StatusBarNotification statusBarNotification) {
        }

        @Override
        public void onNotificationRemoved(StatusBarNotification statusBarNotification) {
        }
    }

    // Error: Misses onNotificationPosted
    private static class MyNotificationListenerService2 extends NotificationListenerService {
        @Override
        public void onNotificationRemoved(StatusBarNotification statusBarNotification) {
        }
    }

    // Error: Misses onNotificationRemoved
    private static class MyNotificationListenerService3 extends NotificationListenerService {
        @Override
        public void onNotificationPosted(StatusBarNotification statusBarNotification) {
        }
    }

    // Error: Missing both; wrong signatures (first has wrong arg count, second has wrong type)
    private static class MyNotificationListenerService4 extends NotificationListenerService {
        public void onNotificationPosted(StatusBarNotification statusBarNotification, int flags) {
        }

        public void onNotificationRemoved(int statusBarNotification) {
        }
    }

    // OK: Inherits from a class which define both
    private static class MyNotificationListenerService5 extends MyNotificationListenerService1 {
    }

    // OK: Inherits from a class which defines only one, but the other one is defined here
    private static class MyNotificationListenerService6 extends MyNotificationListenerService3 {
        @Override
        public void onNotificationRemoved(StatusBarNotification statusBarNotification) {
        }
    }

    // Error: Inheriting from a class which only defines one
    private static class MyNotificationListenerService7 extends MyNotificationListenerService3 {
    }

    // OK: Has target api setting a local version that is high enough
    @TargetApi(21)
    private static class MyNotificationListenerService8 extends NotificationListenerService {
    }

    // OK: Suppressed
    @SuppressLint("OverrideAbstract")
    private static class MyNotificationListenerService9 extends MyNotificationListenerService1 {
    }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can also visit the
[source code](https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/OverrideConcreteDetectorTest.java)
for the unit tests for this check to see additional scenarios.

The above example was automatically extracted from the first unit test
found for this lint check, `OverrideConcreteDetector.test`.
To report a problem with this extracted sample, visit
https://issuetracker.google.com/issues/new?component=192708.

(##) Suppressing

You can suppress false positives using one of the following mechanisms:

* Using a suppression annotation like this on the enclosing
  element:

  ```kt
  // Kotlin
  @Suppress("OverrideAbstract")
  fun method() {
     problematicStatement()
  }
  ```

  or

  ```java
  // Java
  @SuppressWarnings("OverrideAbstract")
  void method() {
     problematicStatement();
  }
  ```

* Using a suppression comment like this on the line above:

  ```kt
  //noinspection OverrideAbstract
  problematicStatement()
  ```

* Using a special `lint.xml` file in the source tree which turns off
  the check in that folder and any sub folder. A simple file might look
  like this:
  ```xml
  &lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;lint&gt;
      &lt;issue id="OverrideAbstract" severity="ignore" /&gt;
  &lt;/lint&gt;
  ```
  Instead of `ignore` you can also change the severity here, for
  example from `error` to `warning`. You can find additional
  documentation on how to filter issues by path, regular expression and
  so on
  [here](https://googlesamples.github.io/android-custom-lint-rules/usage/lintxml.md.html).

* In Gradle projects, using the DSL syntax to configure lint. For
  example, you can use something like
  ```gradle
  lintOptions {
      disable 'OverrideAbstract'
  }
  ```
  In Android projects this should be nested inside an `android { }`
  block.

* For manual invocations of `lint`, using the `--ignore` flag:
  ```
  $ lint --ignore OverrideAbstract ...`
  ```

* Last, but not least, using baselines, as discussed
  [here](https://googlesamples.github.io/android-custom-lint-rules/usage/baselines.md.html).

<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js" charset="utf-8"></script><script src="https://morgan3d.github.io/markdeep/latest/markdeep.min.js" charset="utf-8"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script>